/*
 * Huawei HiNIC PCI Express Linux driver
 * Copyright(c) 2017 Huawei Technologies Co., Ltd
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 */

#ifndef HISEC_COMMON_H
#define HISEC_COMMON_H

#define AEAD_ALG_SALT_LEN_32BIT 32
#define AEAD_ALG_KEY_LEN_UNIT 8
#define AEAD_ALG_KEY_BYTE_PAD 7
#define AEAD_ALG_KEY_LEN_SHIFT_UNIT 3

#define AEAD_ALG_KEY_LEN_128BIT 128
#define AEAD_ALG_KEY_LEN_192BIT 192
#define AEAD_ALG_KEY_LEN_256BIT 256
#define AEAD_ALG_KEY_LEN_512BIT 512

#define AEAD_ALG_AUTH_KEY_LEN_16B 16
#define AEAD_ALG_AUTH_KEY_LEN_24B 24
#define AEAD_ALG_AUTH_KEY_LEN_32B 32
#define AEAD_ALG_AUTH_KEY_LEN_64B 64

#define AES_GCM_KEY_LEN_16B 16
#define AES_GCM_KEY_LEN_24B 24
#define AES_GCM_KEY_LEN_32B 32

#define AEAD_ALG_ICV_LEN_32BIT 32
#define AEAD_ALG_ICV_LEN_64BIT 64
#define AEAD_ALG_ICV_LEN_96BIT 96
#define AEAD_ALG_ICV_LEN_128BIT 128
#define AEAD_ALG_ICV_LEN_192BIT 192
#define AEAD_ALG_ICV_LEN_224BIT 224
#define AEAD_ALG_ICV_LEN_256BIT 256
#define AEAD_ALG_ICV_LEN_384BIT 384
#define AEAD_ALG_ICV_LEN_512BIT 512

#define IPSEC_ESP_IV_8B 8
#define IPSEC_ESP_IV_16B 16

#define HISEC_CRYPTO_XTS_BD_TYPE_XTS_EC 0
#define HISEC_CRYPTO_XTS_BD_TYPE_ONLY_XTS 0
#define HISEC_MAX_REPLAY_WIN_SIZE 64

enum hisec_ipsec_sa_ctx_op {
    HISEC_IPSEC_OP_DEL_SA_CTX,
    HISEC_IPSEC_OP_ADD_SA_CTX,
};

enum hisec_ipsec_offload_mode {
    HISEC_IPSEC_OFFLOAD_MODE_DISABLE,
    HISEC_IPSEC_OFFLOAD_MODE_XFRM,  /* linux XFRM IPsec offload */
    HISEC_IPSEC_OFFLOAD_MODE_HWACC, /* HW IPsec offload accelaration */
};

enum hisec_ipsec_cipher_auth_enable {
    HISEC_IPSEC_AUTH_CIPHER_DISABLE,
    HISEC_IPSEC_ONLY_CIPHER_ENABLE,
    HISEC_IPSEC_ONLY_AUTH_ENABLE,
    HISEC_IPSEC_AUTH_CIPHER_ENABLE,
};

enum hisec_ipsec_mode {
    HISEC_IPSEC_MODE_TRANSPORT,
    HISEC_IPSEC_MODE_TUNNEL,
    HISEC_IPSEC_MODE_NAT_TRAVERSE,
};

enum hisec_ipsec_proto {
    HISEC_IPSEC_PROTO_ESP,
    HISEC_IPSEC_PROTO_AH,

    HISEC_IPSEC_PROTO_MAX
};

enum hisec_ipsec_esp_next_proto {
    HISEC_IPSEC_ESP_NEXT_PROTO_UDP,
    HISEC_IPSEC_ESP_NEXT_PROTO_TCP,
    HISEC_IPSEC_ESP_NEXT_PROTO_IPIP,
    HISEC_IPSEC_ESP_NEXT_PROTO_IPV6,
};

enum hisec_ipsec_esp_iv_size {
    HISEC_IPSEC_ESP_IV_128BIT, /* CBC esp hdr iv = 16byte */
    HISEC_IPSEC_ESP_IV_64BIT,  /* GCM esp hdr iv = 8byte */
};

enum hisec_ipsec_esn_flag {
    HISEC_IPSEC_ESN_FLAG_DISABLE,
    HISEC_IPSEC_ESN_FLAG_ENABLE,
};

enum hisec_ipsec_alg_type {
    HISEC_IPSEC_ALG_AEAD,
    HISEC_IPSEC_ALG_ENC,
    HISEC_IPSEC_ALG_AUTH,
    HISEC_IPSEC_ALG_ENCAUTH,
};

enum hisec_crypto_alg_type {
    HISEC_CRYPTO_ALG_AES_GCM,
    HISEC_CRYPTO_ALG_AES_CBC,
    HISEC_CRYPTO_ALG_AES_CTR,
    HISEC_CRYPTO_ALG_HMAC_SHA1,
    HISEC_CRYPTO_ALG_HMAC_SHA256,
    HISEC_CRYPTO_ALG_HMAC_SHA384,
    HISEC_CRYPTO_ALG_HMAC_SHA512,
    HISEC_CRYPTO_ALG_HMAC_SM3,

    HISEC_CRYPTO_ALG_MAX
};

enum hisec_crypto_hmac_alg_type {
    HISEC_CRYPTO_HMAC_PROHIBIT,
    HISEC_CRYPTO_HMAC_SHA1,
    HISEC_CRYPTO_HMAC_SHA224,
    HISEC_CRYPTO_HMAC_SHA256,
    HISEC_CRYPTO_HMAC_SHA512_224,
    HISEC_CRYPTO_HMAC_SHA512_256,
    HISEC_CRYPTO_HMAC_SHA512_384,
    HISEC_CRYPTO_HMAC_SHA512_512,

    HISEC_CRYPTO_HMAC_MAX
};

enum hisec_crypto_cipher_alg {
    HISEC_CRYPTO_CIPHER_ALG_AES,
    HISEC_CRYPTO_CIPHER_ALG_SM4 = 3,
};

enum hisec_crypto_tx_channel_type {
    HISEC_CRYPTO_TX_CHNL_TYPE_GCM,
    HISEC_CRYPTO_TX_CHNL_TYPE_CBC,
    HISEC_CRYPTO_TX_CHNL_TYPE_ASYM,

    HISEC_CRYPTO_TX_CHNL_TYPE_MAX
};

enum hisec_crypto_cipher_type {
    HISEC_CRYPTO_CIPHER_TYPE_XTS,
    HISEC_CRYPTO_CIPHER_TYPE_CTR,
    HISEC_CRYPTO_CIPHER_TYPE_ECB,
    HISEC_CRYPTO_CIPHER_TYPE_CBC,
    HISEC_CRYPTO_CIPHER_TYPE_GCM = 6,
    HISEC_CRYPTO_CIPHER_TYPE_OFB = 10,
};

enum hisec_crypto_bd_type {
    HISEC_CRYPTO_BD_TYPE_SYM_CBCGCM,
    HISEC_CRYPTO_BD_TYPE_SYM_XTS,
    HISEC_CRYPTO_BD_TYPE_ASYM,
    HISEC_CRYPTO_BD_TYPE_BYPASS,

    HISEC_CRYPTO_BD_TYPE_MAX
};

enum hisec_crypto_xts_ec_num {
    HISEC_CRYPTO_XTS_EC_NUM1 = 1,
    HISEC_CRYPTO_XTS_EC_NUM2 = 2,
    HISEC_CRYPTO_XTS_EC_NUM3 = 3,
    HISEC_CRYPTO_XTS_EC_NUM4 = 4,
    HISEC_CRYPTO_XTS_EC_NUM5 = 5,
    HISEC_CRYPTO_XTS_EC_NUM6 = 6,
    HISEC_CRYPTO_XTS_EC_NUM7 = 7,
    HISEC_CRYPTO_XTS_EC_NUM8 = 8,
    HISEC_CRYPTO_XTS_EC_NUM9 = 9,
    HISEC_CRYPTO_XTS_EC_NUM10 = 10,
    HISEC_CRYPTO_XTS_EC_NUM11 = 11,
    HISEC_CRYPTO_XTS_EC_NUM12 = 12,

    HISEC_CRYPTO_XTS_EC_NUM_MAX
};

enum hisec_crypto_cbcgcm_bd_len {
    HISEC_CRYPTO_CBCGCM_BD_LEN_128B,
    HISEC_CRYPTO_CBCGCM_BD_LEN_160B,
    HISEC_CRYPTO_CBCGCM_BD_LEN_192B,
    HISEC_CRYPTO_CBCGCM_BD_LEN_224B,
    HISEC_CRYPTO_CBCGCM_BD_LEN_256B,
    HISEC_CRYPTO_CBCGCM_BD_LEN_288B,
    HISEC_CRYPTO_CBCGCM_BD_LEN_320B,
};

enum hisec_crypto_xts_bd_len {
    HISEC_CRYPTO_XTS_BD_LEN_128B,
    HISEC_CRYPTO_XTS_BD_LEN_160B,
    HISEC_CRYPTO_XTS_BD_LEN_192B,
    HISEC_CRYPTO_XTS_BD_LEN_224B,
    HISEC_CRYPTO_XTS_BD_LEN_256B,
};

enum hisec_crypto_aes_key_len {
    HISEC_CRYPTO_AES_KEY_LEN_128BIT,
    HISEC_CRYPTO_AES_KEY_LEN_192BIT,
    HISEC_CRYPTO_AES_KEY_LEN_256BIT,
};

enum hisec_crypto_auth_type {
    HISEC_CRYPTO_AUTH_TYPE_HMAC,
    HISEC_CRYPTO_AUTH_TYPE_NORMAL_HASH,
    HISEC_CRYPTO_AUTH_TYPE_PROHIBIT,
    HISEC_CRYPTO_AUTH_TYPE_GMAC = 3,
    HISEC_CRYPTO_AUTH_TYPE_GCM = 6,
};

enum hisec_crypto_decry_status {
    HISEC_CRYPTO_DECRY_SUCCESS,
    HISEC_CRYPTO_DECRY_AUTH_FAILED,
    HISEC_CRYPTO_DECRY_BAD_PROTO,
};

enum hisec_dh_phrase_stage {
    HISEC_DH_STAGE1 = 1,
    HISEC_DH_STAGE2 = 2,

    HISEC_DH_STAGE_MAX
};

enum hisec_dh_group_mode {
    HISEC_DH_MODE_GROUP1 = 1,
    HISEC_DH_MODE_GROUP2 = 2,
    HISEC_DH_MODE_GROUP5 = 5,
    HISEC_DH_MODE_GROUP14 = 14,
    HISEC_DH_MODE_GROUP15 = 15,
    HISEC_DH_MODE_GROUP16 = 16,
    HISEC_DH_MODE_GROUP19 = 19,
    HISEC_DH_MODE_GROUP20 = 20,
    HISEC_DH_MODE_GROUP21 = 21,

    HISEC_DH_MODE_MAX = 22
};

enum crypt_err_code {
    CRYPT_ERR_SUCCESS,
    CRYPT_ERR_FAILED,
    CRYPT_ERR_PARAM
};

typedef enum hisec_ipsec_sad_cmd {
    HISEC_IPSEC_SAD_ADD_SA,
    HISEC_IPSEC_SAD_DEL_SA,
    HISEC_IPSEC_SAD_UPDATE_SA,
    HISEC_IPSEC_SAD_FLUSH_SA,
} hisec_ipsec_sad_cmd_e;

typedef enum hisec_ipsec_spd_cmd {
    HISEC_IPSEC_SPD_ADD_POLICY,
    HISEC_IPSEC_SPD_DEL_POLICY,
    HISEC_IPSEC_SPD_UPDATE_POLICY,
    HISEC_IPSEC_SPD_FLUSH_POLICY,
} hisec_ipsec_spd_cmd_e;

typedef enum hisec_ipsec_spd_action {
    HISEC_IPSEC_SPD_ACTION_BYPASS = 0,
    HISEC_IPSEC_SPD_ACTION_ENCRYPTED = 1,
    HISEC_IPSEC_SPD_ACTION_FWD,
} hisec_ipsec_spd_action_e;

typedef enum hisec_ipsecres_flag {
    HISEC_IPSECRES_ALL = 0,
    HISEC_IPSECRES_SP = 1,
    HISEC_IPSECRES_SA = 2,

    HISEC_IPSECRES_MAX
} hisec_ipsecres_flag_e;

struct hisec_ipsec_alg_info {
    u8 cipher_alg_sel;
    u8 cipher_key_len_sel;
    u8 auth_type;
    u8 cipher_type;

    u8 esp_iv_size;
    u8 sha2_alg_sel;
    u8 sm3_md;
    u8 rsvd0;

    u16 cipher_key_len_byte;
    u16 auth_key_len;   /* in byte */
    u16 auth_trunc_len; /* in byte */
    u16 rsvd1;
    u32 icv_mac_len; /* in byte */

    u32 cipher_key[8];
    u32 auth_key[8];
    u32 salt;
};

#define IPSEC_SA_CTX_SW_DW0_CA_EN_OFS 30
#define IPSEC_SA_CTX_SW_DW0_WORK_MODE_OFS 27
#define IPSEC_SA_CTX_SW_DW0_IPSEC_PROTO_OFS 24
#define IPSEC_SA_CTX_SW_DW0_AUTH_KEY_LEN_OFS 14
#define IPSEC_SA_CTX_SW_DW0_AUTH_TYPE_OFS 10
#define IPSEC_SA_CTX_SW_DW0_CIPHER_TYPE_OFS 6
#define IPSEC_SA_CTX_SW_DW0_CIPHER_KEY_LEN_SEL_OFS 4
#define IPSEC_SA_CTX_SW_DW0_CIPHER_ALG_SEL_OFS 2
#define IPSEC_SA_CTX_SW_DW0_ESP_IV_SIZE_OFS 0

#define IPSEC_SA_CTX_SW_DW1_SM3_MD_OFS 29
#define IPSEC_SA_CTX_SW_DW1_ESN_FLAG_OFS 27
#define IPSEC_SA_CTX_SW_DW1_MAC_LEN_OFS 20
#define IPSEC_SA_CTX_SW_DW1_TFC_PAD_LEN_OFS 12
#define IPSEC_SA_CTX_SW_DW1_TFC_PAD_VAL_OFS 4
#define IPSEC_SA_CTX_SW_DW1_SHA2_ALG_SEL_OFS 0

#define IPSEC_SA_CTX_SW_DW2_AUTH_OFFSET_OFS 16
#define IPSEC_SA_CTX_SW_DW2_CIPHER_OFFSET_OFS 0

#define IPSEC_SA_CTX_SW_DW3_RNG_REP_OFFSET_OFS 16
#define IPSEC_SA_CTX_SW_DW3_ESP_AH_OFFSET_OFS 0

#define HISEC_IPSEC_SA_CTX_SW_DW0(ca_en, work_mode, ipsec_proto, auth_key_len, auth_type, cipher_type,                \
    cipher_key_len_sel, cipher_alg_sel, esp_iv_size)                                                                  \
    (((ca_en) << IPSEC_SA_CTX_SW_DW0_CA_EN_OFS) | ((work_mode) << IPSEC_SA_CTX_SW_DW0_WORK_MODE_OFS) |                \
        ((ipsec_proto) << IPSEC_SA_CTX_SW_DW0_IPSEC_PROTO_OFS) |                                                      \
        ((u32)(auth_key_len) << IPSEC_SA_CTX_SW_DW0_AUTH_KEY_LEN_OFS) |                                               \
        ((auth_type) << IPSEC_SA_CTX_SW_DW0_AUTH_TYPE_OFS) | ((cipher_type) << IPSEC_SA_CTX_SW_DW0_CIPHER_TYPE_OFS) | \
        ((cipher_key_len_sel) << IPSEC_SA_CTX_SW_DW0_CIPHER_KEY_LEN_SEL_OFS) |                                        \
        ((cipher_alg_sel) << IPSEC_SA_CTX_SW_DW0_CIPHER_ALG_SEL_OFS) |                                                \
        ((esp_iv_size) << IPSEC_SA_CTX_SW_DW0_ESP_IV_SIZE_OFS))

#define HISEC_IPSEC_SA_CTX_SW_DW1(sm3_md, esn_flag, mac_len, tfc_pad_len, tfc_pad_val, sha2_alg_sel)                   \
    (((sm3_md) << IPSEC_SA_CTX_SW_DW1_SM3_MD_OFS) | ((esn_flag) << IPSEC_SA_CTX_SW_DW1_ESN_FLAG_OFS) |                 \
        ((u32)(mac_len) << IPSEC_SA_CTX_SW_DW1_MAC_LEN_OFS) | ((tfc_pad_len) << IPSEC_SA_CTX_SW_DW1_TFC_PAD_LEN_OFS) | \
        ((tfc_pad_val) << IPSEC_SA_CTX_SW_DW1_TFC_PAD_VAL_OFS) |                                                       \
        ((sha2_alg_sel) << IPSEC_SA_CTX_SW_DW1_SHA2_ALG_SEL_OFS))

#define HISEC_IPSEC_SA_CTX_SW_DW2(auth_offset, cipher_offset)      \
    (((u32)(auth_offset) << IPSEC_SA_CTX_SW_DW2_AUTH_OFFSET_OFS) | \
        ((u32)(cipher_offset) << IPSEC_SA_CTX_SW_DW2_CIPHER_OFFSET_OFS))

#define HISEC_IPSEC_SA_CTX_SW_DW3(rng_rep_offset, esp_ah_offset)    \
    (((rng_rep_offset) << IPSEC_SA_CTX_SW_DW3_RNG_REP_OFFSET_OFS) | \
        ((esp_ah_offset) << IPSEC_SA_CTX_SW_DW3_ESP_AH_OFFSET_OFS))

#define IPSEC_SA_CTX_ANTI_REP_DW4_WIN_OFS 24
#define IPSEC_SA_CTX_ANTI_REP_DW4_ESN_EN_RX_OFS 23
#define IPSEC_SA_CTX_ANTI_REP_DW10_ESN_EN_TX_OFS 30

#define HISEC_IPSEC_SA_CTX_ANTI_REP_DW4(rep_win, esn_en_rx) \
    (((u32)(rep_win) << IPSEC_SA_CTX_ANTI_REP_DW4_WIN_OFS) | ((esn_en_rx) << IPSEC_SA_CTX_ANTI_REP_DW4_ESN_EN_RX_OFS))

#define HISEC_IPSEC_SA_CTX_ANTI_REP_DW10(esn_en_tx) ((u32)(esn_en_tx) << IPSEC_SA_CTX_ANTI_REP_DW10_ESN_EN_TX_OFS)

#endif
